package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
	"time"

	"homepage-backend/internal/config"
	"homepage-backend/internal/handlers"
	"homepage-backend/internal/services"
)

// 组合中间件
func combineMiddleware(handler http.HandlerFunc) http.HandlerFunc {
	return handlers.CorsMiddleware(handlers.LoggingMiddleware(handler))
}

func main() {
	// 定义命令行参数
	configPath := flag.String("config", "config.json", "配置文件路径")
	port := flag.Int("port", 8080, "服务器监听端口")
	flag.Parse()

	// 支持命令行修改管理员用户名和密码（必须在一切初始化之前）
	if len(os.Args) > 1 && os.Args[1] == "changepwd" {
		fmt.Print("请输入新用户名: ")
		var newUser string
		fmt.Scanln(&newUser)
		fmt.Print("请输入新密码: ")
		var newPwd string
		fmt.Scanln(&newPwd)
		hash, err := config.HashPassword(newPwd)
		if err != nil {
			fmt.Fprintf(os.Stderr, "密码加密失败: %v\n", err)
			os.Exit(1)
		}
		// 先加载原有配置
		_ = config.LoadConfig(*configPath)
		config.GlobalConfig.AdminUser = newUser
		config.GlobalConfig.AdminPassHash = hash
		config.GlobalConfig.JWTSecret = config.RandomString(32) // 刷新jwt密钥，所有token立即失效
		f, err := os.Create(*configPath)
		if err != nil {
			fmt.Fprintf(os.Stderr, "写入配置文件失败: %v\n", err)
			os.Exit(1)
		}
		enc := json.NewEncoder(f)
		enc.SetIndent("", "    ")
		enc.Encode(config.GlobalConfig)
		f.Close()
		fmt.Println("管理员用户名和密码已更新，所有Token已失效！")
		os.Exit(0)
	}

	// 初始化日志服务
	if err := services.InitLogger(); err != nil {
		fmt.Fprintf(os.Stderr, "初始化日志服务失败: %v\n", err)
		os.Exit(1)
	}

	services.LogInfo("正在启动服务器...")

	// 加载配置
	if err := config.LoadConfig(*configPath); err != nil {
		services.LogError("加载配置文件失败: %v", err)
		os.Exit(1)
	}
	services.LogInfo("配置加载完成")

	// 初始化IP查询服务
	if err := services.InitIPSearcher(filepath.Join(".", "ip2region.xdb")); err != nil {
		services.LogError("初始化IP查询服务失败: %v", err)
		os.Exit(1)
	}
	services.LogInfo("IP查询服务初始化完成")

	// 初始化音乐分享服务
	if err := services.InitMusicShareService(); err != nil {
		services.LogError("初始化音乐分享服务失败: %v", err)
		os.Exit(1)
	}
	services.LogInfo("音乐分享服务初始化完成")

	baseURL := config.GlobalConfig.BaseURL
	if baseURL == "" {
		baseURL = "/"
	}

	// 创建路由
	mux := http.NewServeMux()
	mux.HandleFunc(baseURL, combineMiddleware(handlers.HomeHandler))
	mux.HandleFunc(baseURL+"sites", combineMiddleware(handlers.SitesHandler))
	mux.HandleFunc(baseURL+"spider", combineMiddleware(handlers.SpiderHandler))
	mux.HandleFunc(baseURL+"sitemap.xml", combineMiddleware(handlers.SitemapHandler))
	mux.HandleFunc(baseURL+"announcements", combineMiddleware(handlers.AnnouncementHandler))
	mux.HandleFunc(baseURL+"music/share", combineMiddleware(handlers.MusicShareHandler))
	mux.HandleFunc(baseURL+"links", combineMiddleware(handlers.LinkHandler))

	// 后台管理相关接口
	mux.HandleFunc(baseURL+"admin/login", combineMiddleware(handlers.AdminLoginHandler))
	// 下面这些接口需要签权
	mux.HandleFunc(baseURL+"admin/announcements", combineMiddleware(handlers.AdminAuthMiddleware(handlers.AnnouncementHandler)))
	mux.HandleFunc(baseURL+"admin/sites", combineMiddleware(handlers.AdminAuthMiddleware(handlers.SitesHandler)))
	mux.HandleFunc(baseURL+"admin/music/share", combineMiddleware(handlers.AdminAuthMiddleware(handlers.MusicShareHandler)))
	mux.HandleFunc(baseURL+"admin/links", combineMiddleware(handlers.AdminAuthMiddleware(handlers.LinkHandler)))

	// 创建HTTP服务器
	server := &http.Server{
		Addr:    fmt.Sprintf(":%d", *port),
		Handler: mux,
	}

	// 创建一个通道来接收操作系统的信号
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, os.Interrupt, syscall.SIGTERM)

	// 在一个独立的goroutine中启动服务器
	go func() {
		services.LogInfo("服务器正在监听端口%s，基础URL为：%s", server.Addr, baseURL)
		if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			services.LogError("服务器启动失败: %v", err)
			os.Exit(1)
		}
	}()

	// 等待中断信号
	<-stop
	services.LogInfo("关闭服务器...")

	// 创建一个5秒超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 优雅关闭服务器
	if err := server.Shutdown(ctx); err != nil {
		services.LogError("服务器关闭出错: %v", err)
	}

	// 执行清理操作
	services.LogInfo("正在执行清理操作...")
	services.CloseIPSearcher() // 关闭IP查询服务
	services.CloseLogger()     // 关闭日志服务

	services.LogInfo("服务器已成功关闭")
}
